#!/usr/bin/perl -w

#
#  Grabber to search for Bollywood films on cinecurry
#        (www.cinecurry.com)
#
package grabbers::cinecurry;

use LWP::Simple;      # libwww-perl providing simple HTML get actions
use HTML::Entities;
use URI::Escape;
use Text::Levenshtein qw(distance);

use vars qw($opt_h $opt_r $opt_d $opt_i $opt_v $opt_D $opt_M $opt_P);
use Getopt::Std;

my $_rev = '$Rev: 140 $';

# Exports
our $VERSION = "1.0";

sub title
{
	return "Cinecurry";
}
sub desc
{
	return "Search on Cinecurry";
}

sub version
{
	$_rev =~ s/\$//g;
	return $VERSION.", ".$_rev ;
}

sub search 
{
	my $self = shift;
	my $title = shift;
	my $subtitle = shift;
	my $season = shift;
	my $episode = shift;
	my $year = shift;
	my %details;	

	$ref = searchCinecurry($title);
	if(length $ref > 0)
	{
		getCinecurryData(\%details, $ref);
	}
	return %details;
}

sub new
{
    my($class, %args) = @_;
    my $self = bless({}, $class);
    
    return $self;
}

sub trim {
   my ($str) = @_;
   $str =~ s/^\s+//;
   $str =~ s/\s+$//;
   return $str;
}

# returns text within 'data' between 'beg' and 'end' matching strings
sub parseBetween {
   my ($data, $beg, $end)=@_; # grab parameters

   my $ldata = lc($data);
   my $start = index($ldata, lc($beg)) + length($beg);
   my $finish = index($ldata, lc($end), $start);
   if ($start != (length($beg) -1) && $finish != -1) {
      my $result = substr($data, $start, $finish - $start);
      # return w/ decoded numeric character references
      # (see http://www.w3.org/TR/html4/charset.html#h-5.3.1)
      decode_entities($result);
      return $result;
   }
   return "";
}

# get Movie Data
sub getCinecurryData {
   my ($file_details, $movieid)=@_; # grab movieid parameter
   if (defined $opt_d) { printf("# looking for movie id: '%s'\n", $movieid);}

   my $name_link_pat = qr'<a *href="/celebzone/[^>]*>([^<]*)</a>'m;

   # get the search results  page
   my $request = "http://www.cinecurry.com/movie/" . $movieid;
   if (defined $opt_d) { printf("# request: '%s'\n", $request); }
   my $response = get $request;
   if (defined $opt_r) { printf("%s", $response); }

   # parse title and year
   my $year = "";
   my $title = parseBetween($response, "<h1 class=\"m_l_title\">", "</h1>");

   # parse director
   my $data = parseBetween($response, "<h3>Director<\/h3>", "</div>");
   if (!length($data)) {
      $data = parseBetween($response, ">Directors:</h4>", "</div>");
   }
   my $director = join(",", ($data =~ m/$name_link_pat/g));
   $director =~ s/\ +/\ /g; # remove multiple spaces

   # parse writer
   # (Note: this takes the 'first' writer, may want to include others)
   $data = parseBetween($response, ">Writers <a href=\"/wga\">(WGA)</a>:</h5>", "</div>");
   if (!length($data)) {
         $data = parseBetween($response, ">Writer:</h5>", "</div>");
   }
   if (!length($data)) {
         $data = parseBetween($response, ">Writers:</h5>", "</div>");
   }
   my $writer = join(",", ($data =~ m/$name_link_pat/g));

   # parse release date
   my $releasedate = parseBetween($response, "<h3>Release Date</h3>", "</div>");
   if( $releasedate )
   {
      if (defined $opt_d) { printf("# Parsing release date: '%s'\n", $releasedate);}
      $releasedate = parseBetween($releasedate, "single\">", "</span>");
      if (defined $opt_d) { printf("# Parsing release date: '%s'\n", $releasedate);}
      $releasedate =~ s/.*?(\d\d\d\d).*/\1/;
      if (defined $opt_d) { printf("# Parsing release date: '%s'\n", $releasedate);}
   }

   # parse plot
   my $plot = parseBetween($response, "<div class=\"m_l_content_synopsis\">", "</div>");

   if ($plot) {
	# remove any <div> markers
	$plot =~ s/<div [^>]*>//g;
	$plot =~ s/<p>//g;
	$plot =~ s/<\/p>//g;
	$plot =~ s/&#x27;/\'/g;
      # replace name links in plot (example 0388795)
      $plot =~ s/$name_link_pat/$1/g;

      # replace title links
      my $title_link_pat = qr!<a href="/title/[^"]*">([^<]*)</a>!m;
      $plot =~ s/$title_link_pat/$1/g;

      # plot ends at first remaining link
      my $plot_end = index($plot, "<a ");
      if ($plot_end != -1) {
         $plot = substr($plot, 0, $plot_end);
      }
      $plot = trim($plot);
   }

   # parse user rating
   my $userrating = parseBetween($response, ">User Rating:</b>", "</b>");
   $userrating = parseBetween($userrating, "<b>", "/");

   # parse MPAA rating
   my $ratingcountry = "USA";
   my $movierating = trim(parseBetween($response, ">MPAA</a>:</h5>", "</div>"));
   if (!$movierating) {
       $movierating = parseBetween($response, ">Certification:</h5>", "</div>");
       $movierating = parseBetween($movierating, "certificates=$ratingcountry",
                                   "/a>");
       $movierating = parseBetween($movierating, ">", "<");
   }

   # parse movie length
   my $rawruntime = trim(parseBetween($response, ">Runtime:</h4>", "</div>"));
   my $runtime = trim(parseBetween($rawruntime, "", " min"));
   for my $country (@countries) {
      last if ($runtime =~ /^-?\d/);
      $runtime = trim(parseBetween($rawruntime, "$country:", " min"));
   }

   # parse cast
   #  Note: full cast would be from url:
   #    www.imdb.com/title/<movieid>/fullcredits

   my $cast = "";
   $data = parseBetween($response, "<h3>Star Cast</h3>","<h3>");
   if ($data) {
      $cast = join(',', ($data =~ m/$name_link_pat/g));
      $cast = trim($cast);
      $cast =~ s/\ +/\ /g; # remove multiple spaces
   }


   # parse genres
   my $lgenres = "";
   $data = parseBetween($response, "<h5>Genre:</h5>","</div>");
   if ($data) {
      my $genre_pat = qr'/Sections/Genres/(?:[a-z ]+/)*">([^<]+)<'im;
      $lgenres = join(',', ($data =~ /$genre_pat/g));
   }

   # parse countries
   $data = parseBetween($response, "Country:</h5>","</div>");
   my $country_pat = qr'/Sections/Countries/[A-Z]+/">([^<]+)</a>'i;
   my $lcountries = trim(join(",", ($data =~ m/$country_pat/g)));


   # get poster
   my $uri = "";
       $data = parseBetween($response, "<h1 class=\"m_l_title\">", "<\/div>");
       if ($data ne "") {
           $uri = parseBetween($data, "src=\"", "\"");
	}
   $file_details->{PosterUrl} = "http://www.cinecurry.com".$uri;


   # output fields (these field names must match what MythVideo is looking for)
	$file_details->{Title} = $title;
	$file_details->{Director} = $director;
	$file_details->{Plot} = $plot;
	$file_details->{Year} = $releasedate;
	$file_details->{Cast} = $cast;
	$file_details->{Length} = $runtime;
#   print "Title:$title\n";
#   print "Year:$year\n";
#   print "ReleaseDate:$releasedate\n";
#   print "Director:$director\n";
#   print "Plot:$plot\n";
#   print "UserRating:$userrating\n";
#   print "MovieRating:$movierating\n";
#   print "Runtime:$runtime\n";
#   print "Writers: $writer\n";
#   print "Cast:$cast\n";
#   print "Genres: $lgenres\n";
#   print "Countries: $lcountries\n";
}

# dump Movie list:  1 entry per line, each line as 'movieid:Movie Title'
sub searchCinecurry {
   my ($search_title)=@_; # grab parameters

	# if there are more than 4 errors. then maybe we don't want it
	my $best_score = 5;
	my $best_ref = "";
	my $errors;

   # If we wanted to inspect the file for any reason we can do that now

   #
   # Convert filename into a query string
   # (use same rules that Metadata::guesTitle does)
   my $query = $search_title;
   $query =~ s/\ /-/g;
   $query = uri_unescape($query);  # in case it was escaped

   if (!$options) { $options = "" ;}
   if (defined $opt_d) {
      printf("# query: '%s', options: '%s'\n", $query, $options);
   }

   # get the search results  page
   #    some known IMDB options are:
   #         type=[fuzy]         looser search
   #         from_year=[int]     limit matches to year (broken at imdb)
   #         to_year=[int]       limit matches to year (broken at imdb)
   #         sort=[smart]        ??
   #         tv=[no|both|only]   limits between tv and movies (broken at imdb)
   #$options = "tt=on;nm=on;mx=20";  # not exactly clear what these options do
   my $request = "http://www.cinecurry.com/category/seek-movie-search-terms/$query";
   if (defined $opt_d) { printf("# request: '%s'\n", $request); }
   my $response = get $request;
   if (defined $opt_r) {
      print $response;
      exit(0);
   }

   # extract possible matches
   #    possible matches are grouped in several catagories:
   #        exact, partial, and approximate
   my $search_results = parseBetween($response, "<dl class=\"search-results movie-results\">",
                                              "</dl");
   if (defined $opt_r) {
      print "#### Search Results ####\n";
      print $search_results."\n\n";
   }
   # parse movie list from matches
   my $beg = "<div";
   my $end = "</div>";
   my $count = 0;
   my @movies;

   my $data = $search_results;
   # resort to partial matches if no exact
#   if ($data eq "") { $data = $partial_matches; }
   # resort to approximate matches if no exact or partial
#   if ($data eq "") { $data = $approx_matches; }
   if ($data eq "") {
      if (defined $opt_d) { printf("# no results\n"); }
      return;
   }
   my $start = index($data, $beg);
   my $finish = index($data, $end, $start);
   my $year;
   my $type;
   my $title;
   while ($start != -1 && $start < length($data)) {
      $start += length($beg);
      my $entry = substr($data, $start, $finish - $start);
      $start = index($data, $beg, $finish + 1);
      $finish = index($data, $end, $start);
      if (defined $opt_r) {
      	  print "#### Entry ####\n";
      	  print $entry."\n\n";
      }

      my $title = "";
      my $year = "";
      my $type = "";
      my $movienum = "";

      # Some titles are identical, IMDB indicates this by appending /I /II to
      # the release year.
      #   e.g. "Mon meilleur ami" 2006/I vs "Mon meilleur ami" 2006/II
      if ($entry =~ m/<a href="http:\/\/www\.cinecurry\.com\/movie\/(.+)">/i) 
      {
          $movienum = $1;
          if ($entry =~ m/<h2>([^<]*)<\/h2>/i)
          {
             $title = $1;
             
          }
#          $year = $3;
#          $type = $4 if ($4);
      } else {
           if (defined $opt_d) {
               print("Unrecognized entry format ($entry)\n");
           }
           next;
      }

      my $skip = 0;

      # add to array
      if (!$skip) {
		$title =~ s/\"//g;
		$title =~ s/-/ /g;
		$errors = scoreMatch($search_title, $title);
		printf "$movienum: \"$title\" $year\n";
		if($errors < $best_score)
		{
			if($year == $search_year)
			{
				$best_score = $errors - 1;
			}
			else
			{
				$best_score = $errors;
			}
			$best_ref = $movienum;
			printf "  Found better match: ".$title."\n";
		}
		elsif($errors == $best_score)
		{
			if($year == $search_year)
			{
				$best_score = $errors - 1;
				$best_ref = $movienum;
				print "  Found Better Match: $title ($year)\r\n";
			}
		}
      }
   }
   return $best_ref;
}
sub scoreMatch
{
	my $first = shift;
	my $second = shift;
	$first =~ s/[^\w\s]//g;
	$second =~ s/[^\w\s]//g;
	my $errors = distance(lc($first), lc($second));
#	print " Errors between \"$first\" and \"$second\": $errors\r\n";
	return $errors;
}

# vim: set expandtab ts=3 sw=3 :
1;
